%{
#define YYERROR_VERBOSE
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "packetinfo.h"

extern FILE *packetinfoin;

void yyerror(struct packetinfo* info, char *err)
{
    printf("%s\n", err);
}

int packetinfo(struct packetinfo* info)
{
    FILE *cfgfile = fopen("./packet.info", "r");
    if (cfgfile) {
        packetinfoin = cfgfile;
        yyparse(info);
        fclose(cfgfile);
    } else {
        printf("error open file %s\n", "./packet.info");
    }
}
%}

%parse-param {struct packetinfo* info}

%union
{
    char*			str;
    int				num;
    struct table*		table;
    struct clause*		clause;
    struct field*		field;
    struct general*		general;
    struct packetinfo*		info;
}


%token GENERAL_BEGIN SEC_LEVEL VER_PACKET VER_SYSTEM PACKET_FROM PACKET_TO PACKET_NUMBER PACKET_PREV GENERAL_END
%token TABLES_START TABLES_STOP TABLE_START POINT QUOTATION COMA LBR RBR TABLE_PKEYS TABLE_OTHER TABLE_CREATE TABLE_STOP
%token <str> WORD
%token <num> NUMBER
%type <table> TABLES
%type <field> FIELDS
%type <clause> CLAUSE
%type <general> GENERAL
%type <info> INFO

%start INFO

%%
INFO: GENERAL TABLES_START TABLES TABLES_STOP {
    $$ = info;
    $$->general=$1;
    $$->table=$3;
};
GENERAL: GENERAL_BEGIN SEC_LEVEL NUMBER VER_PACKET WORD VER_SYSTEM WORD PACKET_FROM WORD PACKET_TO WORD PACKET_NUMBER NUMBER PACKET_PREV NUMBER GENERAL_END {
    $$ = malloc(sizeof(struct general));
    $$->sec_level=$3;
    $$->ver_packet=$5;
    $$->ver_system=$7;
    $$->from=$9;
    $$->to=$11;
    $$->number=$13;
    $$->prev=$15;
};
TABLES: TABLE_START WORD TABLE_PKEYS QUOTATION FIELDS QUOTATION TABLE_OTHER QUOTATION FIELDS QUOTATION TABLE_CREATE QUOTATION CLAUSE QUOTATION TABLE_STOP {
    $$ = malloc(sizeof(struct table));
    $$->name=$2;
    $$->pkey=$5;
    $$->other=$9;
    $$->clause=$13;
    $$->next=NULL;
} | TABLE_START WORD TABLE_PKEYS QUOTATION FIELDS QUOTATION TABLE_OTHER QUOTATION FIELDS QUOTATION TABLE_CREATE QUOTATION CLAUSE QUOTATION TABLE_STOP TABLES {
    $$ = malloc(sizeof(struct table));
    $$->name=$2;
    $$->pkey=$5;
    $$->other=$9;
    $$->clause=$13;
    $$->next=$16;
};
FIELDS: WORD {
    $$ = malloc(sizeof(struct field));
    $$->name=$1;
    $$->next=NULL;
} | WORD FIELDS {
    $$ = malloc(sizeof(struct field));
    $$->name=$1;
    $$->next=$2;
};
CLAUSE: WORD WORD {
    $$ = malloc(sizeof(struct clause));
    $$->name=$1;
    $$->type=$2;
    $$->size=0;
    $$->digits=0;
    $$->next=NULL;
} | WORD WORD LBR NUMBER RBR {
    $$ = malloc(sizeof(struct clause));
    $$->name=$1;
    $$->type=$2;
    $$->size=$4;
    $$->digits=0;
    $$->next=NULL;
} | WORD WORD LBR NUMBER COMA NUMBER RBR {
    $$ = malloc(sizeof(struct clause));
    $$->name=$1;
    $$->type=$2;
    $$->size=$4;
    $$->digits=$6;
    $$->next=NULL;
} | WORD WORD COMA CLAUSE {
    $$ = malloc(sizeof(struct clause));
    $$->name=$1;
    $$->type=$2;
    $$->size=0;
    $$->digits=0;
    $$->next=$4;
} | WORD WORD LBR NUMBER RBR COMA CLAUSE {
    $$ = malloc(sizeof(struct clause));
    $$->name=$1;
    $$->type=$2;
    $$->size=$4;
    $$->digits=0;
    $$->next=$7;
} | WORD WORD LBR NUMBER COMA NUMBER RBR COMA CLAUSE {
    $$ = malloc(sizeof(struct clause));
    $$->name=$1;
    $$->type=$2;
    $$->size=$4;
    $$->digits=$6;
    $$->next=$9;
};
